package it.tukano.image;

import com.kitfox.svg.RenderableElement;
import com.kitfox.svg.SVGCache;
import com.kitfox.svg.SVGDiagram;
import com.kitfox.svg.SVGElement;
import com.kitfox.svg.SVGException;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Icon;
import javax.swing.ImageIcon;

/**
 * Given a svg file, renders elements of it as icons of variable size. This class
 * requires the svg salamander library to work.
 * @author pgi
 */
public class SvgIconPack {
    private final HashMap<Dimension, HashMap<String, Icon>> cache = new HashMap<Dimension, HashMap<String, Icon>>();
    private final SVGDiagram diagram;
    
    /**
     * Instance initializer
     * @param svgFileUrl the url of a svg file
     */
    public SvgIconPack(URL svgFileUrl) {
        URI uri = SVGCache.getSVGUniverse().loadSVG(svgFileUrl);
        diagram = SVGCache.getSVGUniverse().getDiagram(uri);
    }
    
    /**
     * Returns an image icon that paints a named element of the svg file
     * @param elementName the name of the element to paint
     * @param size the size of the icon
     * @return the requested icon
     */
    public Icon get(String elementName, Dimension size) {
        HashMap<String, Icon> map = cache.get(size);
        if(map == null) cache.put(size, map = new HashMap<String, Icon>());
        Icon icon = map.get(elementName);
        if(icon == null) map.put(elementName, icon = createIcon(elementName, size));
        return icon;
    }
    
    /**
     * Creates an icon for a given svg element and a certain size
     * @param elementName the name of the svg element to paint in the icon
     * @param size the size of the icon (svg element will be scaled to fit)
     * @return the requested icon
     */
    protected Icon createIcon(String elementName, Dimension size) {
        Icon icon = null;
        SVGElement element = diagram.getElement(elementName);
        if(element instanceof RenderableElement) {
            RenderableElement r = (RenderableElement) element;
            try {
                Rectangle bounds = r.getBoundingBox().getBounds();
                if(size == null) size = new Dimension(bounds.width, bounds.height);
                BufferedImage image = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_ARGB);
                Graphics2D graphics = image.createGraphics();
                graphics.setClip(0, 0, size.width, size.height);
                graphics.scale(size.width / bounds.getWidth(), size.height / bounds.getHeight());
                graphics.translate(-bounds.x, -bounds.y);
                graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                diagram.render(graphics);
                icon = new ImageIcon(image);
            } catch (SVGException ex) {
                Logger.getLogger(SvgIconPack.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return icon;
    }
}
